package com.hsurosy.types.design.framework.tree;

import lombok.Getter;
import lombok.Setter;

/**
 * @Author Hsu琛君珩
 * @Date 2025-08-12 3:52
 * @Description 异步资源加载的策略路由器
 * @Version: v1.0.0
 */
public abstract class AbstractMultiThreadStrategyRouter<T, D, R> implements StrategyMapper<T, D, R>, StrategyHandler<T, D, R> {

    // 默认策略处理器
    @Getter
    @Setter
    protected StrategyHandler<T, D, R> defaultStrategyHandler = StrategyHandler.DEFAULT;

    /**
     * 路由方法，根据请求参数和动态上下文选择合适的策略处理器并执行
     * @param requestParameter 请求参数
     * @param dynamicContext 动态上下文
     * @return 策略执行后的结果
     * @throws Exception 如果获取策略处理器或执行时出错
     */
    public R router(T requestParameter, D dynamicContext) throws Exception {
        // 1. 获取策略处理器
        StrategyHandler<T, D, R> strategyHandler = get(requestParameter, dynamicContext);
        // 2. 如果找到了合适的策略处理器，应用策略
        if (null != strategyHandler) return strategyHandler.apply(requestParameter, dynamicContext);
        // 3. 如果没有找到合适的策略，使用默认策略处理器
        return strategyHandler.apply(requestParameter, dynamicContext);
    }

    /**
     * 策略执行入口方法
     * @param requestParameter 请求参数，作为策略执行的主要输入
     * @param dynamicContext   动态上下文，携带额外的运行时数据
     * @return 策略执行的结果
     * @throws Exception 在异步加载或业务处理过程中可能抛出的异常
     */
    @Override
    public R apply(T requestParameter, D dynamicContext) throws Exception {
        // 1. 异步加载数据
        multiThread(requestParameter, dynamicContext);
        // 2. 业务流程受理
        return doApply(requestParameter, dynamicContext);
    }

    /**
     * 异步预处理方法：用于在策略执行前并发加载需要的资源或数据
     * @param requestParameter 请求参数
     * @param dynamicContext 动态上下文
     * @throws Exception 异步加载时可能抛出的异常
     */
    protected abstract void multiThread(T requestParameter, D dynamicContext) throws Exception;

    /**
     * 核心业务执行方法：完成具体的策略逻辑（由子类实现）
     * @param requestParameter 请求参数
     * @param dynamicContext 动态上下文
     * @return 策略执行结果
     * @throws Exception 业务执行过程中的异常
     */
    protected abstract R doApply(T requestParameter, D dynamicContext) throws Exception;

}
